package com.galaxy.user.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.galaxy.common.mybatis.core.page.PageQuery;
import com.galaxy.common.mybatis.core.page.TableDataInfo;
import com.galaxy.user.domain.UserAccount;
import com.galaxy.user.domain.bo.UserAccountBo;
import com.galaxy.user.domain.vo.UserAccountVo;
import com.galaxy.user.mapper.UserAccountMapper;
import com.galaxy.user.service.UserAccountService;
import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount> implements UserAccountService {

    private final UserAccountMapper userAccountMapper;
    private final Converter converter;

    @DS("slave")
    @Override
    public TableDataInfo<UserAccountVo> queryPageList(UserAccountBo bo, PageQuery pageQuery) {
        UserAccount userAccount = converter.convert(bo, UserAccount.class);
        var page = userAccountMapper.selectUserAccountList(userAccount, pageQuery.build());
        List<UserAccountVo> records = page.getRecords().stream()
            .map(account -> converter.convert(account, UserAccountVo.class))
            .collect(Collectors.toList());
        return new TableDataInfo<>(records, page.getTotal());
    }

    @DS("slave")
    @Override
    public List<UserAccountVo> queryList(UserAccountBo bo) {
        UserAccount userAccount = converter.convert(bo, UserAccount.class);
        return userAccountMapper.selectUserAccountList(userAccount).stream()
            .map(account -> converter.convert(account, UserAccountVo.class))
            .collect(Collectors.toList());
    }

    @DS("slave")
    @Override
    public UserAccount queryById(Long id) {
        return userAccountMapper.selectUserAccountById(id);
    }

    @DS("slave")
    @Override
    public UserAccount getInfoByUserId(Long id) {
        return userAccountMapper.selectUserAccountByUserId(id);
    }

    @Override
    public Boolean insertByBo(UserAccountBo bo) {
        UserAccount add = converter.convert(bo, UserAccount.class);
        return userAccountMapper.insert(add) > 0;
    }

    @Override
    public Boolean updateByBo(UserAccountBo bo) {
        UserAccount update = converter.convert(bo, UserAccount.class);
        return userAccountMapper.updateById(update) > 0;
    }

    @Override
    public Boolean updateAvatar(Long userId, Integer points) {
        UserAccount update = new UserAccount();
        update.setUserId(userId);
        update.setPoints(points);
        update.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        LambdaUpdateWrapper<UserAccount> set = new LambdaUpdateWrapper<UserAccount>()
            .set(UserAccount::getPoints, update.getPoints())
            .set(UserAccount::getUpdateTime, update.getUpdateTime())
            .eq(UserAccount::getUserId, update.getUserId());
        return userAccountMapper.update(set) > 0;
    }

    @Override
    public Boolean updateBalance(Long userId, BigDecimal balance) {
        UserAccount update = new UserAccount();
        update.setUserId(userId);
        update.setBalance(balance);
        update.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
            .eq(UserAccount::getUserId, update.getUserId()));
        LambdaUpdateWrapper<UserAccount> set = new LambdaUpdateWrapper<UserAccount>()
            .set(UserAccount::getBalance, userAccount.getBalance().subtract(update.getBalance()))
            .set(UserAccount::getUpdateTime, update.getUpdateTime())
            .eq(UserAccount::getUserId, update.getUserId());
        return userAccountMapper.update(set) > 0;
    }

    @Override
    public Boolean updateBalance1(Long userId, BigDecimal balance) {
        UserAccount update = new UserAccount();
        update.setUserId(userId);
        update.setBalance(balance);
        update.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
            .eq(UserAccount::getUserId, update.getUserId()));

        Integer intValue = update.getBalance().subtract(userAccount.getBalance()).intValue(); // 注意：这会截断小数部分

        LambdaUpdateWrapper<UserAccount> set = new LambdaUpdateWrapper<UserAccount>()
            .set(UserAccount::getBalance, update.getBalance())
            .set(UserAccount::getPoints, userAccount.getPoints()+intValue)
            .set(UserAccount::getUpdateTime, update.getUpdateTime())
            .eq(UserAccount::getUserId, update.getUserId());

        return userAccountMapper.update(set) > 0;
    }

    @Override
    public Boolean updatePoints(Long userId, Integer points) {
        UserAccount update = new UserAccount();
        update.setUserId(userId);
        update.setPoints(points);
        update.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
            .eq(UserAccount::getUserId, update.getUserId()));
        LambdaUpdateWrapper<UserAccount> set = new LambdaUpdateWrapper<UserAccount>()
            .set(UserAccount::getPoints, userAccount.getPoints()+update.getPoints())
            .set(UserAccount::getUpdateTime, update.getUpdateTime())
            .eq(UserAccount::getUserId, update.getUserId());
        return userAccountMapper.update(set) > 0;
    }

    @Override
    public Boolean deleteWithValidByIds(List<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO: Add validation logic here
        }
        return userAccountMapper.deleteBatchIds(ids) > 0;
    }
}
